package com.leaves.exception;

import cn.dev33.satoken.exception.DisableLoginException;
import cn.dev33.satoken.exception.NotLoginException;
import cn.dev33.satoken.exception.NotPermissionException;
import cn.dev33.satoken.exception.NotRoleException;
import com.leaves.response.ApiResult;
import com.leaves.response.ApiResultConstant;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.validation.BindException;
import org.springframework.validation.FieldError;
import org.springframework.web.HttpRequestMethodNotSupportedException;
import org.springframework.web.bind.MethodArgumentNotValidException;
import org.springframework.web.bind.MissingServletRequestParameterException;
import org.springframework.web.bind.annotation.ControllerAdvice;
import org.springframework.web.bind.annotation.ExceptionHandler;
import org.springframework.web.bind.annotation.ResponseBody;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

/**
 * @Author: LEAVES
 * @Date: 2022/5/1 21:05
 * @Version: 1.0
 * @Description: 全局异常处理
 */
@ResponseBody
@ControllerAdvice
public class GlobalException {

    private final static Logger LOGGER = LoggerFactory.getLogger(GlobalException.class);

    /**
     * http请求的方法不正确
     */
    @ExceptionHandler(HttpRequestMethodNotSupportedException.class)
    public Object httpRequestMethodNotSupportedExceptionHandler(HttpRequestMethodNotSupportedException exception) {
        LOGGER.error("http请求的方法不正确:【" + exception.getMessage() + "】");
        return ApiResult.error("HTTP请求的方法不正确：" + exception.getMessage());
    }

    /**
     * 参数校验统一异常处理:针对body传参
     */
    @ExceptionHandler(MethodArgumentNotValidException.class)
    public ApiResult handleBindException(MethodArgumentNotValidException ex) {
        FieldError fieldError = ex.getBindingResult().getFieldError();
        LOGGER.warn("参数校验异常：{}({})", fieldError.getDefaultMessage(), fieldError.getField());
        return ApiResult.error(fieldError.getDefaultMessage());
    }

    /**
     * 参数校验统一异常处理：针对from表单传参
     *
     * @param ex
     * @return
     */
    @ExceptionHandler(BindException.class)
    public ApiResult handleBindExceptionForForm(BindException ex) {
        FieldError fieldError = ex.getBindingResult().getFieldError();
        LOGGER.warn("参数校验异常：{}({})", fieldError.getDefaultMessage(), fieldError.getField());
        return ApiResult.error(fieldError.getDefaultMessage());
    }

    /**
     * 参数校验统一异常处理：针对地址栏传参
     *
     * @param ex
     * @return
     */
    @ExceptionHandler(MissingServletRequestParameterException.class)
    public ApiResult handleMissingServletRequestParameterException(MissingServletRequestParameterException ex, HttpServletRequest request) {
        String parameterName = ex.getParameterName();
        LOGGER.warn("参数校验异常：{}", parameterName);
        return ApiResult.error("参数校验异常:" + parameterName + "值不能为空");
    }

    @ExceptionHandler(MessageCenterException.class)
    public ApiResult messageCenterException(MessageCenterException exception) {
        LOGGER.error("发生异常啦:【" + exception.getMsg() + "】");
        return ApiResult.error(exception.getMsg());
    }

    /**
     * 全局异常拦截（拦截项目中的所有异常）
     *
     * @param e
     * @param request
     * @param response
     * @return
     * @throws Exception
     */

    @ExceptionHandler(Exception.class)
    public ApiResult handlerException(Exception e, HttpServletRequest request, HttpServletResponse response) throws Exception {
        // 打印堆栈，以供调试
        LOGGER.error("---------------全局异常---------------");
        e.printStackTrace();
        // 不同异常返回不同状态码
        ApiResult apiResult;
        if (e instanceof NotLoginException) {    // 如果是未登录异常
            NotLoginException ee = (NotLoginException) e;
            LOGGER.error("" + ee);
            apiResult = ApiResult.notLogin();
            response.setStatus(ApiResultConstant.CODE_NOT_LOGIN);
        } else if (e instanceof NotRoleException) {        // 如果是角色异常
            NotRoleException ee = (NotRoleException) e;
            apiResult = ApiResult.notJur("您暂无此角色：" + ee.getRole());
            response.setStatus(ApiResultConstant.CODE_NOT_JUR);
        } else if (e instanceof NotPermissionException) {    // 如果是权限异常
            NotPermissionException ee = (NotPermissionException) e;
            apiResult = ApiResult.notJur("您暂无无此权限：" + ee.getCode());
            response.setStatus(ApiResultConstant.CODE_NOT_JUR);
        } else if (e instanceof DisableLoginException) {    // 如果是被封禁异常
            DisableLoginException ee = (DisableLoginException) e;
            apiResult = ApiResult.notJur("您的账号已被封禁，将：" + ee.getDisableTime() + "秒后解封");
            response.setStatus(ApiResultConstant.CODE_NOT_JUR);
        } else {    // 普通异常, 输出：500 + 异常信息
            apiResult = ApiResult.error("系统异常，请稍后再试");
            response.setStatus(ApiResultConstant.CODE_ERROR);
        }
        // 返回给前端
        return apiResult;
    }

}
